home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / Xprof / xprof / main.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  13KB  |  452 lines

  1. /*==================================================================
  2.  *      File :          main.c
  3.  *      Package:        Xprof
  4.  *
  5.  *      Author :        Aloke Gupta.
  6.  *
  7.  *  (C) Copyright 1992, Aloke Gupta.
  8.  *==================================================================*/
  9.  
  10. /*
  11.  * main.c: Main function definitions 
  12.  * Functions:
  13.  *    1. main(int argc, char **argv)
  14.  *    2. process_client(char *string, GlobalStats gstats)
  15.  *    3. process_server(char *string, GlobalStats gstats)
  16.  *    4. print_stats(FILE *fp)
  17.  *    5. process_stats(FILE *fp,long min, long max, long *distbn, Grain grain,
  18.  *        long maxbuckets, StatsType statstype)
  19.  *    6. Signal handlers defined by ONSIGNAL(function, string, terminate)
  20.  *    7. t_search(char *string, char *token)
  21.  */
  22.  
  23. static char copyright[] =
  24. "@(#) Copyright (c) 1992 Aloke Gupta.\n\
  25. All rights reserved.\n";
  26.  
  27. #define VERSION    "1.01"
  28. static char *xprof_version = VERSION;
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <signal.h>
  33. #include<sys/time.h>
  34. #include "common.h"
  35.  
  36. void set_net_latency( /* double */);
  37. void set_net_speed  ( /* double */);
  38.  
  39. #define FILENAMESIZE    128
  40.  
  41. /*
  42.  * The following are signal handlers defined at the end of this file
  43.  */
  44. void onhangup();
  45. void onintr();
  46. void onquit();
  47. void onfpe();
  48. void onbus();
  49. void onsegv();
  50. void onxcpu();
  51.  
  52. int debuglevel        = 0;
  53. int verboselevel    = 2;
  54. int trapsignal        = TRUE;    /* Trap signals ? */
  55. Boolean profileflag = FALSE;    /* This flag should be set only if a parameters
  56.                    file is specified on the command line */
  57. long _LINE_NUM      = 0;    /* The current line number */
  58.  
  59. GlobalStats globalstats;
  60.  
  61. Usage(prog_name, badfield) 
  62. char *prog_name;
  63. char *badfield;
  64. {
  65.     if (badfield != NULL)
  66.         fprintf(stderr,"\n\t** Unknown option: \"%s\" **\n",badfield);
  67.     fprintf(stderr, " Usage: %-8s ", prog_name);
  68.     fprintf(stderr, "-d<debuglevel>         ");
  69.     fprintf(stderr, "-v<verboselevel>       ");
  70.     fprintf(stderr, "-p<perffile>");
  71.     fprintf(stderr, "\n                 ");
  72.     fprintf(stderr, "-b<num_buckets>        ");
  73.     fprintf(stderr, "-s<trapsignal>         ");
  74.     fprintf(stderr, "\n                 ");
  75.     fprintf(stderr, "-S<Net Speed (Bytes/s> ");
  76.     fprintf(stderr, "-L<Net Latency (ms)>   ");
  77.     fprintf(stderr, "[filename]\n\n");
  78.     exit(1);
  79. }
  80.  
  81. main(argc,argv)
  82. int argc;
  83. char *argv[];
  84. {
  85.     char in_string[MAXSTRINGSIZE];
  86.     char *str_ptr;
  87.     int i;
  88.     char filename[FILENAMESIZE];
  89.     FILE *fp=stdin;        /* File pointer to the input file */
  90.     char perffile[FILENAMESIZE];
  91.     FILE *pp;
  92.  
  93.     /*
  94.      * Process the command line arguments
  95.      */
  96.     for (i = 1; i < argc; i++) {
  97.     if (argv[i][0] == '-') {    /* Argument is a flag */
  98.         switch(argv[i][1]) {
  99.         case 'b':
  100.             if (strlen(&argv[i][1]) == 1)
  101.              MAXBUCKETS_SIZE = 4096;
  102.             else MAXBUCKETS_SIZE = atoi(&argv[i][2]);
  103.             break;
  104.         case 'd':        /* Set the debug level */
  105.             if (strlen(&argv[i][1]) == 1)
  106.              debuglevel = 1;
  107.             else debuglevel = atoi(&argv[i][2]);
  108.             break;
  109.         case 'p':
  110.             strcpy(perffile, &argv[i][2]);
  111.             if ((pp = fopen(perffile,"r")) == NULL) 
  112.              fprintf(stderr,"Error: Can't open initialization file:%s\n"
  113.                                 ,perffile);
  114.             else { 
  115.             parse_parameters(pp);
  116.             init_profile();
  117.             profileflag = TRUE;    /* Generate profile */
  118.             }
  119.             break;
  120.         case 's':            /* Trap signals ?*/
  121.             if (strlen(&argv[i][1]) == 1)
  122.                 trapsignal = TRUE;
  123.             else {
  124.                 int flag = atoi(&argv[i][2]);
  125.                 if (flag == 0) trapsignal = FALSE;
  126.                 else trapsignal = TRUE;
  127.             }
  128.             break;
  129.         case 'v':        /* Set the verbosity level */
  130.             if (strlen(&argv[i][1]) == 1)
  131.              verboselevel = 1;
  132.             else verboselevel = atoi(&argv[i][2]);
  133.             break;
  134.         case 'S':        /* Set the network speed */
  135.             if (strlen(&argv[i][1]) >= 1)
  136.             set_net_speed  ((double) atof(&argv[i][2]) );
  137.             break;
  138.         case 'L':        /* Set the network latency */
  139.             if (strlen(&argv[i][1]) >= 1)
  140.             set_net_latency((double) atof(&argv[i][2]) );
  141.             break;
  142.         default:
  143.             Usage(argv[0], argv[i]);
  144.             break;
  145.         }
  146.     }
  147.     else {                /* Assume that argument is a filename */
  148.         strcpy(filename, argv[i]);
  149.         if (fp == stdin) {    /* Has fp been initialized already ?*/
  150.           if ((fp = fopen(filename,"r")) == NULL) {
  151.         fprintf(stderr,"Error: Can't open input file: %s\n",filename);
  152.         exit(1);
  153.           }
  154.         }
  155.         else Usage(argv[0], filename);
  156.     }
  157.     }
  158.  
  159.     {
  160.       char hostname[128];
  161.       struct timeval tp;
  162.       struct timezone tzp;
  163.  
  164.       gethostname (hostname, 128);
  165.       printf("\"%s\", version %s running on %s.\n",
  166.           argv[0], xprof_version, hostname);
  167.       gettimeofday(&tp, &tzp);
  168.       printf("Date: %s\n", ctime (&tp.tv_sec));
  169.     }
  170.     if (fp == stdin) printf("** Input accepted from stdin **\n");
  171.  
  172.     /*
  173.      * Set up the signal handlers. 
  174.      */
  175.     if (trapsignal == TRUE) {
  176.     signal(SIGHUP,  onhangup);
  177.     signal(SIGINT,  onintr);
  178.     signal(SIGQUIT, onquit);
  179.     signal(SIGFPE,  onfpe);
  180.     signal(SIGBUS,  onbus);
  181.     signal(SIGSEGV, onsegv);
  182.     signal(SIGXCPU, onxcpu);
  183.     }
  184.  
  185.     /* Main string processing loop */
  186.  
  187.     while ( fgets(in_string, MAXSTRINGSIZE, fp) != NULL) {
  188.     _LINE_NUM++;
  189.     if    (strstr(in_string,"Client ") != NULL) {
  190.         if (debuglevel >= 1)
  191.             printf("%s",in_string);
  192.         process_client(in_string, &globalstats);
  193.     }
  194.     else if ((str_ptr = strstr(in_string,"REQUEST")) != NULL) {
  195.         if (debuglevel >= 1)
  196.             printf("%s",in_string);
  197.         process_request(fp, str_ptr, &globalstats);
  198.     }
  199.     else if (strstr(in_string,"<-- X11 Server") != NULL) {
  200.         if (debuglevel >= 1)
  201.             printf("%s",in_string);
  202.         process_server(in_string, &globalstats);
  203.     }
  204.     else if ((str_ptr = strstr(in_string,"REPLY")) != NULL) {
  205.         if (debuglevel >= 1)
  206.             printf("%s",in_string);
  207.         process_reply(fp, str_ptr, &globalstats);
  208.     }
  209.     else if ((str_ptr = strstr(in_string,"EVENT")) != NULL) {
  210.         if (debuglevel >= 1)
  211.             printf("%s",in_string);
  212.         process_event(fp, str_ptr, &globalstats);
  213.     }
  214.     else if ((str_ptr = strstr(in_string,"ERROR")) != NULL) {
  215.         if (debuglevel >= 1)
  216.             printf("%s",in_string);
  217.         process_error(fp, str_ptr, &globalstats);
  218.     }
  219.     }
  220.  
  221.     /* Print out the statistics collected before exiting */
  222.     print_stats(stdout);
  223.     return(0);
  224. }
  225.  
  226. /* Process the line corresponding to a message from the client 
  227.  * The format of the line is:
  228.  * <timestamp> Client [Client number] --> <Num_bytes> bytes
  229.  *
  230.  * The Client number field is optional
  231.  */
  232. process_client(string, gstats)
  233. char *string;
  234. GlobalStats *gstats;
  235. {
  236.     float time; /* The time stamp is in the form xx.yy seconds*/
  237.     char junk1[80],junk2[80],junk3[80],junk4[80];
  238.     int client_num;        /* This is ignored in the current program */
  239.     unsigned num_bytes=0;
  240.     int i;
  241.  
  242.     i=sscanf(string,"%f %s %s %d %s %d %s", &time, junk1, junk2,
  243.                 &client_num, junk3, &num_bytes, junk4);
  244.     if (i != 7) {
  245.     i=sscanf(string,"%f %s %s %s %d %s", &time, junk1, junk2,
  246.                 junk3, &num_bytes, junk4);
  247.     if (i !=6) return ;
  248.     }
  249.     /* 
  250.      * Now update the global structures for the client
  251.      */
  252.     gstats->last_time       = gstats->current_time;
  253.     gstats->current_time  = (long) (time * 1000);
  254.     gstats->client_bytes += num_bytes;
  255.     return;
  256. }
  257.  
  258. /* Process the line corresponding to a message from the server 
  259.  * The format of the line is:
  260.  *
  261.  * <timestamp>                <Num_bytes> bytes <-- X11 Server
  262.  *
  263.  */
  264.  
  265. process_server(string, gstats)
  266. char *string;
  267. GlobalStats *gstats;
  268. {
  269.     float time; /* The time stamp is in the form xx.yy seconds*/
  270.     char junk1[80], junk2[80], junk3[80], junk4[80];
  271.     unsigned num_bytes=0;
  272.     int i;
  273.  
  274.     i = sscanf(string,"%f %s %d %s %s %s", &time,junk1,&num_bytes,
  275.             junk2, junk3, junk4);
  276.     if (i < 6) return;
  277.     /* 
  278.      * Now update the global structures for the server
  279.      */
  280.     gstats->last_time       = gstats->current_time;
  281.     gstats->current_time  = (long) (time * 1000);
  282.     gstats->server_bytes += num_bytes;
  283.     return;
  284. }
  285.  
  286. /* 
  287.  * print_stats(): Final printout function.
  288.  * It consults the global variable "globalstats" It is not passed any
  289.  * arguments because it may be called by the interrupt service routine.
  290.  */
  291. print_stats(fp)
  292. FILE *fp;
  293. {
  294.     fprintf(fp,"Final line number: %d\n",_LINE_NUM);
  295.     fprintf(fp,"Final time stamp : %.2f Seconds\n",
  296.             (float) globalstats.current_time / 1000.0);
  297.     fprintf(fp,"Messages transferred (In Bytes):\n");
  298.     fprintf(fp,"    Client     Server   Requests    Replies     Events     Errors");
  299.     fprintf(fp,"\n%10lu %10lu %10lu %10lu %10lu %10lu\n",
  300.     globalstats.client_bytes,  globalstats.server_bytes,
  301.     globalstats.request_bytes, globalstats.reply_bytes,
  302.     globalstats.event_bytes,   globalstats.error_bytes);
  303.  
  304.     print_request_stats(fp);
  305.     print_reply_stats(fp);
  306.     print_event_stats(fp);
  307.     print_error_stats(fp);
  308.  
  309.     if (profileflag) print_profile_stats(fp);
  310. }
  311.  
  312. /*
  313.  * Print out the statistics of a distribution consisting of maxbuckets buckets
  314.  */
  315. process_stats(fp, min, max, distbn, grain, maxbuckets, statstype)
  316. FILE *fp;
  317. long min;
  318. long max;
  319. long distbn[];
  320. Grain grain;
  321. long maxbuckets;
  322. StatsType statstype;
  323. {
  324.     long number=0;    /* Total number of data points. This may be different
  325.                from the number of corresponding messages.*/
  326.     double mean=0.0, variance=0.0, std_dev=0.0;
  327.     long    median=0;
  328.     long    mode=0;
  329.     long    mode_freq=0;
  330.     long    n=0;
  331.     double sum=0.0, sum_sq=0.0;
  332.     double tmp;
  333.     int     i;
  334.     long datapoint;
  335.  
  336.     /* Collect the total number of data points */
  337.     for (i = 0; i < maxbuckets; i++)
  338.     number += distbn[i];
  339.  
  340.     /* Collect the sums, sum of squares, mode, and median */
  341.     for (i = 0; i < maxbuckets; i++) {
  342.     if (statstype == LOG2)    datapoint = (long) myexp2(i);
  343.     else            datapoint = i;
  344.     n     += distbn[i];
  345.     tmp    = (double) distbn[i] * datapoint * (double) grain;
  346.     sum   += (double) tmp;
  347.     sum_sq+= (double) tmp * datapoint * (double) grain;
  348.     if (distbn[i] > mode_freq) {
  349.         mode = datapoint;
  350.         mode_freq = distbn[i];
  351.     }
  352.     if (n <= (number / 2)) 
  353.         median = datapoint;
  354.     }
  355.     if (number > 0) {
  356.     mean     = (double) sum / (double) number;
  357.     variance = (double) (sum_sq / (double) number) - (mean * mean);
  358.     std_dev  = (double) sqrt(variance);
  359.     }
  360.  
  361.     fprintf(fp,"%-15s ",""); 
  362.     fprintf(fp,"%6s %15s %7s %7s %10s %10s\n", "Number", "Range      ",
  363.                 "Mode", "Median", "Mean", "Std. Dev.");
  364.     fprintf(fp,"%-15s ", "(All points)");
  365.     fprintf(fp,"%6ld %7ld-%-7ld %7ld %7ld %10.2f %10.2f\n",
  366.         number, min *(long) grain, max *(long) grain, mode * (long) grain,
  367.         median * (long) grain, mean, std_dev);
  368.     /*
  369.      * Now print out the statistics for all cases except zero interarrival time
  370.      * The same sum and sum_sq can be recycled, since it has not accumalated the
  371.      * zero case anyway !!
  372.      */
  373.      mean = variance = std_dev = 0.0;
  374.      n = median = mode = mode_freq = 0;
  375.      min = max;    
  376.  
  377.     /* Collect the sums and the sum of squares */
  378.     number -= distbn[0];
  379.     if (number > 0) {
  380.     for (i = 1; i < maxbuckets; i++) {
  381.         if (statstype == LOG2)    datapoint = (long) myexp2(i);
  382.         else            datapoint = i;
  383.         if (distbn[i] > 0) {
  384.         n    += distbn[i];
  385.         if (min > datapoint) min = datapoint;
  386.         }
  387.  
  388.         if (distbn[i] > mode_freq) {
  389.         mode = datapoint;
  390.         mode_freq = distbn[i];
  391.         }
  392.         if (n <= (number / 2)) 
  393.         median = datapoint;
  394.     }
  395.     mean     = (double) sum / (double) number;
  396.     variance = (double) (sum_sq / (double) number) - (mean * mean);
  397.     std_dev  = (double) sqrt(variance);
  398.  
  399.     fprintf(fp,"%-15s ", "(Zeros removed)");
  400.     fprintf(fp,"%6ld %7ld-%-7ld %7ld %7ld %10.2f %10.2f\n",
  401.         number, min * (long) grain, max * (long) grain,
  402.         mode * (long) grain, median * (long) grain, mean, std_dev);
  403.     }
  404. }
  405.  
  406. /* t_search
  407.    Look for existence of token string in the initial position of another string 
  408.    Returns 1 on success, 0 otherwise.
  409. */
  410. int t_search(string, token)
  411. char *string, *token;
  412. {
  413.     while (*token) {
  414.     if ((*token != *string) || !(*string))
  415.         return (0); /* Return if there is a mismatch or we run out of
  416.                     characters in the string */
  417.     token  ++; string ++;
  418.     }
  419.     return (1);         /* Succesful return */
  420. }
  421.  
  422. /*
  423.  * Signal handler routines are defined here
  424.  * In order to force a printout AND continue execution execute the command
  425.  * kill -1 <process-number> from the shell.
  426.  */
  427. #define ONSIGNAL(function, signame, terminate) void function() {\
  428.     sighandler(signame, terminate); \
  429. }
  430.  
  431. ONSIGNAL(onhangup, "Hangup",            FALSE);
  432. ONSIGNAL(onintr,   "Interrupt",            TRUE);
  433. ONSIGNAL(onquit,   "Quit",            TRUE);
  434. ONSIGNAL(onfpe,    "Floating point exception",    TRUE);
  435. ONSIGNAL(onbus,    "Bus Error",         TRUE);
  436. ONSIGNAL(onsegv,   "Segmentation violation",    TRUE);
  437. ONSIGNAL(onxcpu,   "Cpu limit exceeded",    TRUE);
  438.  
  439. sighandler(signame, terminate)
  440. char *signame;
  441. Boolean terminate;
  442. {
  443.     fflush(stdout);
  444.     fprintf(stderr, "\t=== %s signal trapped ===\n", signame);
  445.     fflush(stderr);
  446.     print_stats(stderr);
  447.     fflush(stderr);
  448.     fflush(stdout);
  449.     if (terminate == TRUE)
  450.     abort();
  451. }
  452.